package com.puzzlebazar.client.squaregrid.view;

import com.google.gwt.user.client.ui.Widget;
import com.puzzlebazar.client.util.Vec2i;

public class Drawable {

	private Vec2i  vertexFromLoc;
	private Vec2i  vertexToLoc;
	private final String name; 
	private Widget widget;
	private Vec2i  relativePos = new Vec2i(1,1);
	private Vec2i  sizeOffset = new Vec2i(0,0);	

	/**
	 * Creates a drawable
	 * 
	 * @param name Name of the drawable for future reference (can be null)
	 */
	public Drawable(String name) {
		this.name = name;
	}

	/**
	 * Creates a drawable within a single cell
	 * 
	 * @param cell Location of the cell
	 * @param name Name of the drawable for future reference (can be null)
	 */
	public Drawable(Vec2i cell, String name) {
		setCell( cell );
		this.name = name;
	}	

	/**
	 * Sets a unique cell for this drawable
	 * 
	 * @param cell Cell location
	 */
	public void setCell( Vec2i cell ) {
		this.vertexFromLoc = new Vec2i(cell);
		this.vertexToLoc = new Vec2i(cell.x+1, cell.y+1);		
	}
	
	/**
	 * Sets a rectangle of cells for this drawable
	 * 
	 * @param cellFrom Location at one corner of the rectangle
	 * @param cellTo Location diagonally opposite
	 */
	public void setCellRectangle( Vec2i cellFrom, Vec2i cellTo ) {	
		this.vertexFromLoc = Vec2i.getTopLeftVertex( cellFrom, cellTo );
		this.vertexToLoc = Vec2i.getBottomRightVertex( cellFrom, cellTo );
	}
	
	/**
	 * Sets a unique vertex for this drawable
	 * 
	 * @param vertex Vertex location
	 */
	public void setVertex( Vec2i vertex ) {
		this.vertexFromLoc = new Vec2i(vertex);
		this.vertexToLoc = new Vec2i(vertex);		
	}

	/**
	 * Sets a rectangle of vertices for this drawable
	 * 
	 * @param vertexFrom Location of a vertex at one corner of the rectangle
	 * @param vertexTo Location of the vertex diagonally opposite
	 */
	public void setVertexRectangle(Vec2i vertexFrom, Vec2i vertexTo) {
		this.vertexFromLoc = Vec2i.getTopLeft(vertexFrom, vertexTo);
		this.vertexToLoc = Vec2i.getBottomRight(vertexFrom, vertexTo);
	}

	
	/**
	 * Sets a unique vertical edge for this drawable
	 * 
	 * @param topVertex The top vertex of the edge
	 */
	public void setVerticalEdge( Vec2i topVertex ) {
		this.vertexFromLoc = new Vec2i(topVertex);
		this.vertexToLoc = new Vec2i(topVertex.x, topVertex.y+1);
	}
	
	/**
	 * Sets a unique horizontal edge for this drawable
	 * 
	 * @param leftVertex The left vertex of the edge
	 */
	public void setHorizontalEdge( Vec2i leftVertex ) {
		this.vertexFromLoc = new Vec2i(leftVertex);
		this.vertexToLoc = new Vec2i(leftVertex.x+1, leftVertex.y);		
	}
	
	/**
	 * @return The top-left corner cell of the drawable 
	 */
	public Vec2i getVertexFromLoc() {
		return vertexFromLoc;
	}

	/**
	 * @return The bottom-right corner cell of the drawable 
	 */
	public Vec2i getVertexToLoc() {
		return vertexToLoc;
	}

	/**
	 * Updates the size of the widget. The passed width and height should
	 * correspond to actual size, in pixels between the top-left and 
	 * bottom-right vertices of the grid associated with this widget, INCLUDING
	 * the pixels at these vertices. Use getVertexFromLoc() and getVertexToLoc(). 
	 * When used together with updateSize, these methods will draw a single-cell
	 * drawable so that it doesn't touch any grid lines.
	 * 
	 * @param w New width
	 * @param h New height
	 */
	public void updateSize( int w, int h ) {
		if( widget != null ) widget.setPixelSize(w + sizeOffset.x-2, h + sizeOffset.y-2);
	}

	/**
	 * When used together with updateSize, these methods will draw a single-cell
	 * drawable so that it doesn't touch any grid lines.
	 * 
	 * 
	 * @return The position of the widget relative to the position of its top-left vertex (in pixels)
	 */
	public final Vec2i getRelativePos() {
		return relativePos;
	}

	/**
	 * Sets the position offset to fine-tune widget location
	 * 
	 * @param posOffset The position offset to apply
	 */
	public void setPosOffset(Vec2i posOffset) {
		this.relativePos = new Vec2i(posOffset.x+1, posOffset.y+1);
	}

	/**
	 * Sets the size offset (increases or decreases in size) to fine-tune
	 * the widget positioning
	 * 
	 * @param sizeOffset The new size offset
	 */
	public void setSizeOffset(Vec2i sizeOffset) {
		this.sizeOffset = new Vec2i(sizeOffset);
	}

	/**
	 * @return The top-level widget created for this drawable
	 */
	public Widget getWidget() {
		return widget;
	}
	
	/**
	 * Configures position and size offset so that the widget
	 * "bleeds" over the grid. A bleedsize of 1 makes a single cell
	 *  widget precisely overlap the grid lines.
	 * 
	 * @param bleedSize The bleed size, in pixel (positive to expand, negative to contract)
	 */
	public void setBleed( int bleedSize ) {
		this.relativePos = new Vec2i( -bleedSize+1, -bleedSize+1 );
		this.sizeOffset = new Vec2i( 2*bleedSize, 2*bleedSize );
	}
	
	/**
	 * @return The name of this drawable
	 */
	public String getName() {
		return name;
	}

	/**
	 * Allows a derived class to set the widget associated with this drawable
	 * 
	 * @param widget The widget to set
	 */
	protected void setWidget(Widget widget) {
		this.widget = widget;
	}	
	
}
